<?php
// +----------------------------------------------------------------------
// | HkCms 后台菜单模型
// +----------------------------------------------------------------------
// | Copyright (c) 2012-2019 http://www.hkcms.cn, All rights reserved.
// +----------------------------------------------------------------------
// | Author: 广州恒企教育科技有限公司 <admin@hkcms.cn>
// +----------------------------------------------------------------------

namespace app\admin\model;

use common\model\Model;

class Menu extends Model
{
    protected static $__instance;
    public static function getInterface()
    {
        if (static::$__instance instanceof static) {
            return static::$__instance;
        }
        return static::$__instance = new static();
    }

    /**
     * 获取菜单
     * @return array
     */
    public function getMenuList()
    {
        $items['0changyong'] = array(
            "id" => "",
            "name" => "常用菜单",
            "parent" => "changyong",
            "url" => url("login/changyong"),
        );
        foreach (model('admin/AdminPanel')->getAllPanel(\app\admin\service\User::getInstance()->id) as $r) {
            $items[$r['mid'] . '0changyong'] = array(
                "icon" => "",
                "id" => $r['mid'] . '0changyong',
                "name" => $r['name'],
                "parent" => "changyong",
                "url" => url($r['url']),
            );
        }
        $changyong = array(
            "changyong" => array(
                "icon" => "",
                "id" => "changyong",
                "name" => "常用",
                "parent" => "",
                "url" => "",
                "items" => $items
            )
        );
        $data = $this->getTree(0);
        return array_merge($changyong, $data ? $data : array());
    }

    /**
     * 取得树形结构的菜单
     * @param integer $myid
     * @param string $parent
     * @param integer $Level
     * @return array
     */
    public function getTree($myid, $parent = "", $Level = 1)
    {
        $data = $this->adminMenu($myid);
        $Level++;
        $ret = null;
        if (is_array($data)) {
            foreach ($data as $a) {
                $id = $a['id'];
                $name = $a['app'];
                $controller = $a['controller'];
                $action = $a['action'];
                //附带参数
                $param = "menuid=".$id;
                if ($a['parameter']) {
                    $param = $param .'&'. $a['parameter'];
                }
                $array = array(
                    "icon" => "",
                    "id" => $id . $name,
                    "name" => $a['name'],
                    "parent" => $parent,
                    "url" => url("{$name}/{$controller}/{$action}", $param),
                );
                $ret[$id . $name] = $array;
                $child = $this->getTree($a['id'], $id, $Level);
                //由于后台管理界面只支持三层，超出的不层级的不显示
                if ($child && $Level <= 3) {
                    $ret[$id . $name]['items'] = $child;
                }
            }
        }
        return $ret;
    }

    /**
     * 按父ID查找菜单子项
     * @param $parentid
     * @param bool $with_self
     * @return array|false|\PDOStatement|string|\think\Collection
     */
    public function adminMenu($parentid, $with_self = false)
    {
        //父节点ID
        $parentid = (int) $parentid;
        $result = $this->where(array('parentid' => $parentid, 'status' => 1))->order(['listorder'=>'asc','id'=>'asc'])->select()->toArray();
        if (empty($result)) {
            $result = array();
        }
        if ($with_self) {
            $parentInfo = $this->where(array('id' => $parentid))->find();
            $result2[] = $parentInfo ? $parentInfo->toArray() : array();
            $result = array_merge($result2, $result);
        }
        //是否超级管理员
        if (\app\admin\service\User::getInstance()->isAdministrator()) {
            //如果角色为 1 直接通过
            return $result;
        }
        $array = array();
        //子角色列表
        $child = explode(',', model("admin/Role")->getArrchildid(\app\admin\service\User::getInstance()->role_id));
        foreach ($result as $v) {
            //方法
            $action = $v['action'];
            //条件
            $where = array('app' => $v['app'], 'controller' => $v['controller'], 'action' => $action, 'role_id' => array('IN', $child));
            //如果是菜单项
            if ($v['type'] == 0) {
                $where['controller'] .= $v['id'];
                $where['action'] .= $v['id'];
            }
            //public开头的通过
            if (preg_match('/^public_/', $action)) {
                $array[] = $v;
            } else {
                if (preg_match('/^ajax_([a-z]+)_/', $action, $_match)) {
                    $action = $_match[1];
                }
                //是否有权限
                if (model('admin/Access')->isCompetence($where)) {
                    $array[] = $v;
                }
            }
        }
        return $array;
    }

    /**
     * 获取菜单导航
     */
    public function getMenu()
    {
        $menuid = input('menuid', 0, 'intval');
        cookie(["prefix" => ""]);
        $menuid = $menuid ? $menuid : cookie("menuid", "");
        $info_1 = $this->field("id,action,app,controller,parentid,parameter,type,name")->where(array("id" => $menuid))->select()->toArray();
        $find_1 = $this->field("id,action,app,controller,parentid,parameter,type,name")->where(array("parentid" => $menuid, "status" => 1))->select()->toArray();
        $info = array();
        $find = array();
        foreach ($info_1 as $k=>$v) {

            $info[$v['id']] = $v;
        }
        foreach ($find_1 as $k=>$v) {

            $find[$v['id']] = $v;
        }
     
        if ($find) {
            array_unshift($find, $info[$menuid]);
        } else {
            $find = $info;
        }
        foreach ($find as $k => $v) {
            $find[$k]['parameter'] = "menuid={$menuid}&".$find[$k]['parameter'];
        }
        return $find;
    }

    /**
     * 模块安装时进行菜单注册
     * @param array $data
     * @param array $config
     * @param int $parentid
     * @return bool
     */
    public function installModuleMenu(array $data, array $config, $parentid = 0)
    {
        if (empty($data) || !is_array($data)) {
            $this->error = '没有数据！';
            return false;
        }
        if (empty($config)) {
            $this->error = '模块配置信息为空！';
            return false;
        }
        // 默认安装时父级ID,本地模块管理菜单
        $defaultMenuParentid = $this->where(array('app' => 'Admin', 'controller' => 'Module', 'action' => 'local'))->value('id')? : 42;
        // 安装模块名称
        $moduleNama = $config['module'];
        foreach ($data as $rs) {
            if (empty($rs['route'])) {
                $this->error = '菜单信息配置有误，route 不能为空！';
                return false;
            }
            $route = $this->menuRoute($rs['route']);
            $pid = $parentid ? : ((is_null($rs['parentid']) || !isset($rs['parentid'])) ? (int) $defaultMenuParentid : $rs['parentid']);
            $newData = array_merge(array(
                'name' => $rs['name'],
                'parentid' => $pid,
                'type' => isset($rs['type']) ? $rs['type'] : 1,
                'status' => isset($rs['status']) ? $rs['status'] : 0,
                'remark' => isset($rs['remark'])? $rs['remark']: '',
                'listorder' => isset($rs['listorder'])? $rs['listorder'] : 0,
            ), $route);

            $validate = validate('Menu');
            if (!$validate->check($newData)) {
                $this->error = '菜单信息配置有误，' . $validate->getError();
                return false;
            }
            $newId = $this->allowField(true)->insertGetId($newData);
            //是否有子菜单
            if (!empty($rs['child'])) {
                if ($this->installModuleMenu($rs['child'], $config, $newId) !== true) {
                    return false;
                }
            }
        }
        return true;
    }

    /**
     * 把模块安装时，Menu.php中配置的route进行转换
     * @param $route
     * @param $moduleNama
     * @return array
     */
    private function menuRoute($route, $moduleNama='')
    {
        $route = explode('/', $route, 3);
        if (count($route) < 3) {
            array_unshift($route, $moduleNama);
        }
        $data = array(
            'app' => $route[0],
            'controller' => $route[1],
            'action' => $route[2],
        );
        return $data;
    }

    /**
     * 更新缓存
     * @return array|bool
     */
    public function menu_cache()
    {
        $data = $this->order('listorder')->select()->toArray();
        if (empty($data)) {
            return false;
        }
        $cache = array();
        foreach ($data as $rs) {
            $cache[$rs['id']] = $rs;
        }
        cache('Menu', $cache);
        return $cache;
    }
}